#include <string>
#include <iostream>
#include <cmath> 

// For terminal delay
#include <chrono>
#include <thread>

#include <fstream>
#include <algorithm> 
#include <queue>

#include "game.h"

Game::Game()
{
    // 使用默认皮肤（skin1）
    this->mCurrentSkinIndex = 0;
    this->setSkinSymbol(0);
    
    // Separate the screen to three windows
    this->mWindows.resize(3);
    initscr();
    // If there wasn't any key pressed don't wait for keypress
    nodelay(stdscr, true);
    // Turn on keypad control
    keypad(stdscr, true);
    // No echo for the key pressed
    noecho();
    // No cursor show
    curs_set(0);
    // Get screen and board parameters
    getmaxyx(stdscr, this->mScreenHeight, this->mScreenWidth);
    this->mGameBoardWidth = this->mScreenWidth - this->mInstructionWidth;
    this->mGameBoardHeight = this->mScreenHeight - this->mInformationHeight;

    this->createInformationBoard();
    this->createGameBoard();
    this->createInstructionBoard();

    // Initialize the leader board to be all zeros
    this->mLeaderBoard.assign(this->mNumLeaders, 0);
}

Game::Game(int skinIndex)
{
    // 使用指定的皮肤索引
    this->mCurrentSkinIndex = skinIndex;
    this->setSkinSymbol(skinIndex);
    
    // Separate the screen to three windows
    this->mWindows.resize(3);
    initscr();
    // If there wasn't any key pressed don't wait for keypress
    nodelay(stdscr, true);
    // Turn on keypad control
    keypad(stdscr, true);
    // No echo for the key pressed
    noecho();
    // No cursor show
    curs_set(0);
    // Get screen and board parameters
    getmaxyx(stdscr, this->mScreenHeight, this->mScreenWidth);
    this->mGameBoardWidth = this->mScreenWidth - this->mInstructionWidth;
    this->mGameBoardHeight = this->mScreenHeight - this->mInformationHeight;

    this->createInformationBoard();
    this->createGameBoard();
    this->createInstructionBoard();

    // Initialize the leader board to be all zeros
    this->mLeaderBoard.assign(this->mNumLeaders, 0);
}

Game::~Game()
{
    for (int i = 0; i < this->mWindows.size(); i ++)
    {
        delwin(this->mWindows[i]);
    }
    endwin();
}

void Game::createInformationBoard()
{
    int startY = 0;
    int startX = 0;
    this->mWindows[0] = newwin(this->mInformationHeight, this->mScreenWidth, startY, startX);
}

void Game::renderInformationBoard() const
{
    mvwprintw(this->mWindows[0], 1, 1, "Welcome to The Snake Game!");
    mvwprintw(this->mWindows[0], 2, 1, "Authors: Jiang Yiyang, Mei Zhaoguo, Wang Lianwen");
    mvwprintw(this->mWindows[0], 3, 1, "Website: https://gitee.com/jyy16/snakegame");
    mvwprintw(this->mWindows[0], 4, 1, "Implemented using C++ and libncurses library.");
    wrefresh(this->mWindows[0]);
}

void Game::createGameBoard()
{
    int startY = this->mInformationHeight;
    int startX = 0;
    this->mWindows[1] = newwin(this->mScreenHeight - this->mInformationHeight, this->mScreenWidth - this->mInstructionWidth, startY, startX);
}

void Game::renderGameBoard() const
{
    wrefresh(this->mWindows[1]);
}

void Game::createInstructionBoard()
{
    int startY = this->mInformationHeight;
    int startX = this->mScreenWidth - this->mInstructionWidth;
    this->mWindows[2] = newwin(this->mScreenHeight - this->mInformationHeight, this->mInstructionWidth, startY, startX);
}

void Game::renderInstructionBoard() const
{
    mvwprintw(this->mWindows[2], 1, 1, "Manual");

    mvwprintw(this->mWindows[2], 3, 1, "Up: W");
    mvwprintw(this->mWindows[2], 4, 1, "Down: S");
    mvwprintw(this->mWindows[2], 5, 1, "Left: A");
    mvwprintw(this->mWindows[2], 6, 1, "Right: D");
    mvwprintw(this->mWindows[2], 7, 1, "jump: J+Dir");
    mvwprintw(this->mWindows[2], 8, 1, "Pause: P");

    mvwprintw(this->mWindows[2], 9, 1, "Difficulty");
    mvwprintw(this->mWindows[2], 12, 1, "Points");

    wrefresh(this->mWindows[2]);
}


void Game::renderLeaderBoard() const
{
    // If there is not too much space, skip rendering the leader board 
    if (this->mScreenHeight - this->mInformationHeight - 14 - 2 < 3 * 2)
    {
        return;
    }
    mvwprintw(this->mWindows[2], 14, 1, "Leader Board");
    std::string pointString;
    std::string rank;
    for (int i = 0; i < std::min(this->mNumLeaders, this->mScreenHeight - this->mInformationHeight - 14 - 2); i ++)
    {
        pointString = std::to_string(this->mLeaderBoard[i]);
        rank = "#" + std::to_string(i + 1) + ":";
        mvwprintw(this->mWindows[2], 14 + (i + 1), 1, rank.c_str());
        mvwprintw(this->mWindows[2], 14 + (i + 1), 5, pointString.c_str());
    }
    wrefresh(this->mWindows[2]);
}

bool Game::renderRestartMenu() const
{
    WINDOW * menu;
    int width = this->mGameBoardWidth * 0.5;
    int height = this->mGameBoardHeight * 0.5;
    int startX = this->mGameBoardWidth * 0.25;
    int startY = this->mGameBoardHeight * 0.25 + this->mInformationHeight;

    menu = newwin(height, width, startY, startX);
    box(menu, 0, 0);
    std::vector<std::string> menuItems = {"Restart", "Quit"};

    int index = 0;
    int offset = 4;
    mvwprintw(menu, 1, 1, "Your Final Score:");
    std::string pointString = std::to_string(this->mPoints + this->mBonusPoints);
    mvwprintw(menu, 2, 1, pointString.c_str());
    wattron(menu, A_STANDOUT);
    mvwprintw(menu, 0 + offset, 1, menuItems[0].c_str());
    wattroff(menu, A_STANDOUT);
    mvwprintw(menu, 1 + offset, 1, menuItems[1].c_str());

    wrefresh(menu);

    int key;
    while (true)
    {
        key = getch();
        switch(key)
        {
            case 'W':
            case 'w':
            case KEY_UP:
            {
                mvwprintw(menu, index + offset, 1, menuItems[index].c_str());
                index --;
                index = (index < 0) ? menuItems.size() - 1 : index;
                wattron(menu, A_STANDOUT);
                mvwprintw(menu, index + offset, 1, menuItems[index].c_str());
                wattroff(menu, A_STANDOUT);
                break;
            }
            case 'S':
            case 's':
            case KEY_DOWN:
            {
                mvwprintw(menu, index + offset, 1, menuItems[index].c_str());
                index ++;
                index = (index > menuItems.size() - 1) ? 0 : index;
                wattron(menu, A_STANDOUT);
                mvwprintw(menu, index + offset, 1, menuItems[index].c_str());
                wattroff(menu, A_STANDOUT);
                break;
            }
        }
        wrefresh(menu);
        if (key == ' ' || key == 10)
        {
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    delwin(menu);

    if (index == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
    
}

void Game::renderPoints() const
{
    std::string pointString = std::to_string(this->mPoints) + " + " + std::to_string(this->mBonusPoints);
    mvwprintw(this->mWindows[2], 13, 1, pointString.c_str());
    wrefresh(this->mWindows[2]);
}

void Game::renderDifficulty() const
{
    std::string difficultyString = std::to_string(this->mDifficulty);
    mvwprintw(this->mWindows[2], 10, 1, difficultyString.c_str());
    wrefresh(this->mWindows[2]);
}

void Game::initializeGame()
{
    this->mPtrSnake.reset(new Snake(this->mGameBoardWidth, this->mGameBoardHeight, this->mInitialSnakeLength));
    this->createRamdonFood();
    this->createReadomObstacles();//新增创建随机障碍物
    this->mPtrSnake->senseFood(this->mFood);
    this->mDifficulty = 0;
    this->mPoints = 0;
    this->mDelay = this->mBaseDelay;
    this->mBonusPoints = 0;
}

void Game::createRamdonFood()
{
    std::vector<SnakeBody> availableGrids;
    for (int i = 1; i < this->mGameBoardHeight - 1; i ++)
    {
        for (int j = 1; j < this->mGameBoardWidth - 1; j ++)
        {
            if(this->mPtrSnake->isPartOfSnake(j, i))
            {
                continue;
            }
            bool isObstaclePosition = std::any_of(mObstacles.begin(), mObstacles.end(),
                [j, i](const SnakeBody& obs) {
                    return obs.getX() == j && obs.getY() == i;
                });
            
            if (!isObstaclePosition)
            {
                availableGrids.push_back(SnakeBody(j, i));
            }
        }
    }

    // Randomly select a grid that is not occupied by the snake
    int random_idx = std::rand() % availableGrids.size();
    this->mFood = availableGrids[random_idx];

    //Randomly decide whether to give bonus direction
    float randomFloat = static_cast<float>(std::rand()) / (float)RAND_MAX;
    if (randomFloat < this->mBonusProbability) 
    {
        int foodX = this->mFood.getX();
        int foodY = this->mFood.getY();

        std::vector<Direction> availableDirections;

        if (foodX > 1)
        {
            availableDirections.push_back(Direction::Right);
        }
        if (foodX < this->mGameBoardWidth - 2)
        {
            availableDirections.push_back(Direction::Left);
        }
        if (foodY > 1)
        {
            availableDirections.push_back(Direction::Down);
        }
        if (foodY < this->mGameBoardHeight - 2)
        {
            availableDirections.push_back(Direction::Up);
        }

        if (!availableDirections.empty())
        {
            int randomDirectionIdx = std::rand() % availableDirections.size();
            Direction randomDirection = availableDirections[randomDirectionIdx];
            this->mFood.setBonusDirection(randomDirection);
        }
    }
}

void Game::renderFood() const
{
    //Bonus direction
    char foodSymbol = this->mFood.hasBonusDirection() ? '*' : this->mFoodSymbol;
    mvwaddch(this->mWindows[1], this->mFood.getY(), this->mFood.getX(), foodSymbol);

    if (this->mFood.hasBonusDirection())
    {
        char directionSymbol;
        int offsetX = 0;
        int offsetY = 0;
        switch (this->mFood.getBonusDirection())
        {
            case Direction::Up:
            {
                directionSymbol = '^';
                offsetY = 1;
                break;
            }
            case Direction::Down:
            {
                directionSymbol = 'v';
                offsetY = -1;
                break;      
            }
            case Direction::Left:
            {
                directionSymbol = '<';
                offsetX = 1;
                break;
            }
            case Direction::Right:
            {
                directionSymbol = '>';
                offsetX = -1;
                break;
            }
        }

        mvwaddch(this->mWindows[1], this->mFood.getY() + offsetY, this->mFood.getX() + offsetX, directionSymbol);
    }

    wrefresh(this->mWindows[1]);
}

void Game::renderSnake() const
{
    int snakeLength = this->mPtrSnake->getLength();
    std::vector<SnakeBody>& snake = this->mPtrSnake->getSnake();
    for (int i = 0; i < snakeLength; i ++)
    {
        mvwaddch(this->mWindows[1], snake[i].getY(), snake[i].getX(), this->mCurrentSnakeSymbol);
    }
    wrefresh(this->mWindows[1]);
}

bool Game::controlSnake() 
{
    int key;
    bool hasTurnedThisFrame = false;
    
    while ((key = getch()) != ERR)
    {   

        // 检查是否按下暂停键
        if (key == 'p' || key == 'P')
        {
            this->togglePause();
            continue;
        }
        
        // 如果游戏已暂停，检查是否按下退出键
        if (this->mIsPaused)
        {
            if (key == 'q' || key == 'Q')
            {
                return true;  // 请求退出游戏
            }
            continue;
        }
        
        // 处理跳跃技能
        if (key == 'j' || key == 'J')
        {
            this->mLastBypassKeyPressFrame = this->mFrameCounter;
            continue; // J键不是转向，处理后继续检查缓冲区
        }

        // 如果本帧已转弯，则忽略后续方向键
        if (hasTurnedThisFrame)
        {
            continue;
        }

        // 处理方向键，逻辑和上次修复后一样
        switch(key)
        {
            case 'W': case 'w': case KEY_UP:
                if (this->mPtrSnake->changeDirection(Direction::Up)) { hasTurnedThisFrame = true; }
                break;
            case 'S': case 's': case KEY_DOWN:
                if (this->mPtrSnake->changeDirection(Direction::Down)) { hasTurnedThisFrame = true; }
                break;
            case 'A': case 'a': case KEY_LEFT:
                if (this->mPtrSnake->changeDirection(Direction::Left)) { hasTurnedThisFrame = true; }
                break;
            case 'D': case 'd': case KEY_RIGHT:
                if (this->mPtrSnake->changeDirection(Direction::Right)) { hasTurnedThisFrame = true; }
                break;
        }
    }
    
    return false;  // 不退出游戏
}

void Game::renderBoards() const
{
    for (int i = 0; i < this->mWindows.size(); i ++)
    {
        werase(this->mWindows[i]);
    }
    this->renderInformationBoard();
    this->renderGameBoard();
    this->renderInstructionBoard();
    for (int i = 0; i < this->mWindows.size(); i ++)
    {
        box(this->mWindows[i], 0, 0);
        wrefresh(this->mWindows[i]);
    }

    this->renderLeaderBoard();
}


void Game::adjustDelay()
{
    this->mDifficulty = this->mPoints / 5;
    if (mPoints % 5 == 0)
    {
        this->mDelay = this->mBaseDelay * pow(0.75, this->mDifficulty);
        // 根据新的难度等级重新生成障碍物
        this->createReadomObstacles();
    }
}

void Game::runGame()
{
    this->mFrameCounter = 0;
    this->mLastBypassKeyPressFrame = -1;
    this->mIsPaused = false;  // 重置暂停状态

    while (true)
    {
        // 1. 游戏循环开始，帧数+1
        this->mFrameCounter++;

        // 2. 处理输入
        bool shouldExit = this->controlSnake();
        if (shouldExit)
        {
            break;  // 用户在暂停时选择退出
        }
        
        // 3. 如果游戏暂停，跳过游戏逻辑更新
        if (this->mIsPaused)
        {
            this->renderPauseMenu();
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            continue;
        }

        werase(this->mWindows[1]);
        box(this->mWindows[1], 0, 0);
        
        SnakeBody newHead = this->mPtrSnake->createNewHead();

        bool willHitObstacle = false;
        for (const auto& obs : mObstacles) {
            if (newHead == obs) {
                willHitObstacle = true;
                break;
            }
        }
        
        bool willEatBonus = false;
        if (this->mPtrSnake->touchFood() && this->mFood.hasBonusDirection())
        {
            willEatBonus = (this->mPtrSnake->getCurrentDirection() == this->mFood.getBonusDirection());
        }

        // 3. 【核心决策逻辑】
        bool bypassWindowActive = (this->mLastBypassKeyPressFrame > 0) && 
                                  (this->mFrameCounter - this->mLastBypassKeyPressFrame <= this->mBypassInputWindow);

        if (willHitObstacle && bypassWindowActive)
        {
            // 情况A：执行穿墙
            this->mPtrSnake->moveFoward(); 
            this->mPtrSnake->shorten();    

            // 【新增逻辑】在这里扣除分数
            if (this->mPoints > 0)
            {
                this->mPoints -= 1;
            }

            this->mLastBypassKeyPressFrame = -1;

            if (this->mPtrSnake->getLength() < 1) {
                break; 
            }
        }
        else
        {
            // 情况B：正常移动和吃食物
            bool eatFood = this->mPtrSnake->moveFoward();
            
            if (this->mPtrSnake->checkCollision() || this->mPtrSnake->checkObstacleCollision(this->mObstacles)) {
                break;
            }

            if (eatFood)
            {
                if (willEatBonus)
                {
                    this->mBonusPoints += this->mBonusScore;
                }

                this->mPoints += 1;
                this->createRamdonFood();
                this->mPtrSnake->senseFood(this->mFood);
                this->adjustDelay();
            }
        }

        // 4. 渲染逻辑
        this->renderObstacles();
        this->renderSnake();
        this->renderFood();
        this->renderDifficulty();
        this->renderPoints();
        
        std::this_thread::sleep_for(std::chrono::milliseconds(this->mDelay));
        refresh();
    }
}

void Game::renderObstacles() const
{
    for (const auto& obs : mObstacles)
    {
        // 使用 'X' 作为障碍物符号
        mvwaddch(this->mWindows[1], obs.getY(), obs.getX(), 'X'); 
    }
}

void Game::startGame()
{
    refresh();
    bool choice;
    while (true)
    {
        this->readLeaderBoard();
        this->renderBoards();
        this->initializeGame();
        this->runGame();
        this->updateLeaderBoard();
        this->writeLeaderBoard();
        choice = this->renderRestartMenu();
        if (choice == false)
        {
            break;
        }
    }
}

// https://en.cppreference.com/w/cpp/io/basic_fstream
bool Game::readLeaderBoard()
{
    std::fstream fhand(this->mRecordBoardFilePath, fhand.binary | fhand.in);
    if (!fhand.is_open())
    {
        return false;
    }
    int temp;
    int i = 0;
    while ((!fhand.eof()) && (i < mNumLeaders))
    {
        fhand.read(reinterpret_cast<char*>(&temp), sizeof(temp));
        this->mLeaderBoard[i] = temp;
        i ++;
    }
    fhand.close();
    return true;
}

bool Game::updateLeaderBoard()
{
    bool updated = false;
    int newScore = this->mPoints + this->mBonusPoints;
    for (int i = 0; i < this->mNumLeaders; i ++)
    {
        if (this->mLeaderBoard[i] >= newScore)
        {
            continue;
        }
        int oldScore = this->mLeaderBoard[i];
        this->mLeaderBoard[i] = newScore;
        newScore = oldScore;
        updated = true;
    }
    return updated;
}

bool Game::writeLeaderBoard()
{
    // trunc: clear the data file
    std::fstream fhand(this->mRecordBoardFilePath, fhand.binary | fhand.trunc | fhand.out);
    if (!fhand.is_open())
    {
        return false;
    }
    for (int i = 0; i < this->mNumLeaders; i ++)
    {
        fhand.write(reinterpret_cast<char*>(&this->mLeaderBoard[i]), sizeof(this->mLeaderBoard[i]));;
    }
    fhand.close();
    return true;
}

void Game::createReadomObstacles()
{
    mObstacles.clear();
    
    // 根据难度等级计算障碍物数量
    // 使用与速度相同的倍数公式：1/0.75^difficulty
    int baseObstacles = 5; // 基础障碍物数量
    double speedMultiplier = pow(0.75, this->mDifficulty);
    int numObstacles = static_cast<int>(baseObstacles / speedMultiplier + 0.5); // 四舍五入取整
    
    // 限制最大障碍物数量，避免过多
    if (numObstacles > 20) {
        numObstacles = 20;
    }
    
    // 获取蛇头位置
    SnakeBody snakeHead = mPtrSnake->getHead();
    int headX = snakeHead.getX();
    int headY = snakeHead.getY();
    
    // 定义安全距离（根据难度调整）
    int safeDistance = std::max(3, 6 - this->mDifficulty); // 难度越高，安全距离越小
    
    int tries = 0;
    int maxTries = 100; 
    
    while (mObstacles.size() < numObstacles && tries < maxTries)
    {
        int x = std::rand() % (mGameBoardWidth - 2) + 1; 
        int y = std::rand() % (mGameBoardHeight - 2) + 1;

        SnakeBody candidate(x, y);
        // 检查障碍物是否与蛇或食物冲突
        bool conflict = false;
        
        // 检查是否与蛇身或食物冲突
        if(mPtrSnake->isPartOfSnake(x, y) || (mFood.getX() == x && mFood.getY() == y))
        {
            conflict = true;
        }
        
        // 检查是否离蛇头太近（安全距离检查）
        if (!conflict)
        {
            int distanceToHead = abs(x - headX) + abs(y - headY); // 曼哈顿距离
            if (distanceToHead < safeDistance)
            {
                conflict = true;
            }
        }
        
        // 检查是否离食物太近（避免围困食物）
        if (!conflict)
        {
            int distanceToFood = abs(x - mFood.getX()) + abs(y - mFood.getY());
            if (distanceToFood < 2) // 食物周围至少保留1格距离
            {
                conflict = true;
            }
        }
        
        // 检查是否会形成不可达的区域（简单检查：避免在角落或边缘密集放置）
        if (!conflict)
        {
            // 检查候选位置周围是否已有太多障碍物
            int nearbyObstacles = 0;
            for (const auto& obstacle : mObstacles)
            {
                int distanceToObstacle = abs(x - obstacle.getX()) + abs(y - obstacle.getY());
                if (distanceToObstacle <= 2)
                {
                    nearbyObstacles++;
                }
            }
            
            // 如果周围障碍物过多，跳过这个位置
            if (nearbyObstacles >= 3)
            {
                conflict = true;
            }
        }
        
        if(!conflict)
        {
            mObstacles.push_back(candidate);
        }
        tries++;
    }
    
    // 最终检查：确保食物仍然可达
    if (!isFoodReachable())
    {
        // 如果食物不可达，减少障碍物数量
        while (mObstacles.size() > 0 && !isFoodReachable())
        {
            mObstacles.pop_back();
        }
    }
}

// 检查食物是否可达（使用BFS算法）
bool Game::isFoodReachable() const
{
    // 获取蛇头位置和食物位置
    SnakeBody snakeHead = mPtrSnake->getHead();
    int startX = snakeHead.getX();
    int startY = snakeHead.getY();
    int foodX = mFood.getX();
    int foodY = mFood.getY();
    
    // 如果蛇头就在食物位置，直接返回true
    if (startX == foodX && startY == foodY)
    {
        return true;
    }
    
    // 创建访问标记数组
    std::vector<std::vector<bool>> visited(mGameBoardWidth, std::vector<bool>(mGameBoardHeight, false));
    
    // 标记障碍物和蛇身为不可访问
    for (const auto& obstacle : mObstacles)
    {
        if (obstacle.getX() > 0 && obstacle.getX() < mGameBoardWidth - 1 &&
            obstacle.getY() > 0 && obstacle.getY() < mGameBoardHeight - 1)
        {
            visited[obstacle.getX()][obstacle.getY()] = true;
        }
    }
    
    // 标记蛇身为不可访问（除了蛇头）
    std::vector<SnakeBody>& snakeBody = mPtrSnake->getSnake();
    for (int i = 1; i < snakeBody.size(); i++) // 跳过蛇头
    {
        int x = snakeBody[i].getX();
        int y = snakeBody[i].getY();
        if (x > 0 && x < mGameBoardWidth - 1 && y > 0 && y < mGameBoardHeight - 1)
        {
            visited[x][y] = true;
        }
    }
    
    // 标记边界为不可访问
    for (int x = 0; x < mGameBoardWidth; x++)
    {
        visited[x][0] = true;
        visited[x][mGameBoardHeight - 1] = true;
    }
    for (int y = 0; y < mGameBoardHeight; y++)
    {
        visited[0][y] = true;
        visited[mGameBoardWidth - 1][y] = true;
    }
    
    // BFS搜索
    std::queue<std::pair<int, int>> queue;
    queue.push({startX, startY});
    visited[startX][startY] = true;
    
    // 四个方向
    int dx[] = {0, 0, 1, -1};
    int dy[] = {1, -1, 0, 0};
    
    while (!queue.empty())
    {
        auto [x, y] = queue.front();
        queue.pop();
        
        // 检查是否到达食物
        if (x == foodX && y == foodY)
        {
            return true;
        }
        
        // 探索四个方向
        for (int i = 0; i < 4; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            
            // 检查边界
            if (nx >= 0 && nx < mGameBoardWidth && ny >= 0 && ny < mGameBoardHeight)
            {
                if (!visited[nx][ny])
                {
                    visited[nx][ny] = true;
                    queue.push({nx, ny});
                }
            }
        }
    }
    
    return false; // 无法到达食物
}

// 皮肤相关方法实现
void Game::setSkinSymbol(int skinIndex)
{
    this->mCurrentSkinIndex = skinIndex;
    this->mCurrentSnakeSymbol = getSkinSymbol(skinIndex);
}

char Game::getSkinSymbol(int skinIndex) const
{
    switch (skinIndex)
    {
        case 0:  // skin1 - Python皮肤
            return '@';
        case 1:  // skin2 - Pip3皮肤
            return '$';  // 使用$代替￥，因为￥在某些终端可能显示不正确
        case 2:  // skin3 - Anaconda皮肤
            return '~';
        default:
            return '@';  // 默认符号
    }
}

// 暂停相关方法实现
void Game::togglePause()
{
    this->mIsPaused = !this->mIsPaused;
}

void Game::renderPauseMenu() const
{
    // 清空游戏窗口
    werase(this->mWindows[1]);
    box(this->mWindows[1], 0, 0);
    
    // 在游戏窗口中央显示暂停信息
    int centerX = this->mGameBoardWidth / 2;
    int centerY = this->mGameBoardHeight / 2;
    
    mvwprintw(this->mWindows[1], centerY - 2, centerX - 5, "GAME PAUSED");
    mvwprintw(this->mWindows[1], centerY, centerX - 8, "Press P to Resume");
    mvwprintw(this->mWindows[1], centerY + 1, centerX - 8, "Press Q to Quit");
    
    wrefresh(this->mWindows[1]);
}

bool Game::isPaused() const
{
    return this->mIsPaused;
}






